//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// Set extra attributes for object.
//

# include "StdAfx.h"
# include "SetRgnExtra.h"
# include "UndoRedo.h"
# include "Label.h"

template<typename TExtra>
class CChangeExtraAction : public CEditAction {
  public:
	CChangeExtraAction (rgn_t & _rgn, const string_t & _strName, TExtra (rgn_extra_t::* _pExtraParam), const TExtra & _New) :
		m_rgn (_rgn),
		m_pExtraParam (_pExtraParam),
		m_Prev (_rgn.pExtra ? (* _rgn.pExtra).*_pExtraParam : NULL),
		m_New (_New),
		m_bWasModified ((_rgn.dwFlags & rgn_t::fModified) != 0)
	{
		CCritSec::CLock lock (g_cs);

		m_strName.append ("change ");
		m_strName.append (_strName);
		m_strName.append (" for [");
		GetHintText (m_rgn, m_strName);
		m_strName.append ("]");
	}

	virtual void GetName (string_t & _str) const {_str.append (m_strName);}
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do () {
		CCritSec::CLock lock (g_cs);

		// Change item.
		(* m_rgn.pExtra).*m_pExtraParam = m_New;

		m_rgn.dwFlags |= rgn_t::fModified;

		return true;
	}
	virtual void Undo () {
		CCritSec::CLock lock (g_cs);

		// Revert item.
		(* m_rgn.pExtra).*m_pExtraParam = m_Prev;

		if (! m_bWasModified)
			m_rgn.dwFlags &= ~rgn_t::fModified;
	}
	virtual void Redo () {CChangeExtraAction::Do ();}

  private:
	rgn_t & m_rgn;
	TExtra (rgn_extra_t::* const m_pExtraParam);
	string_t m_strName;

	TExtra const m_Prev;
	TExtra const m_New;

	bool const m_bWasModified;
};

/////////////////////////////////////////////////////////////////

void SetObjectExtra (rgn_t & _rgn, const string_t & _strExtra) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "extra",       & rgn_extra_t::strExtra,       _strExtra));
}

void SetObjectPANumber (rgn_t & _rgn, const string_t & _strNumber) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "number",      & rgn_extra_t::strNumber,      _strNumber));
}

void SetObjectPAStreet (rgn_t & _rgn, const string_t & _strStreet) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "street",      & rgn_extra_t::strStreetDesc,  _strStreet));
}

void SetObjectHWEDescription (rgn_t & _rgn, const string_t & _strHWEDescrition) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "description", & rgn_extra_t::strStreetDesc,  _strHWEDescrition));
}

void SetObjectPhone    (rgn_t & _rgn, const string_t & _strPhone) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "phone",       & rgn_extra_t::strPhone,       _strPhone));
}

void SetObjectFax      (rgn_t & _rgn, const string_t & _strFax) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "fax",         & rgn_extra_t::strFax,         _strFax));
}

void SetObjectEmail    (rgn_t & _rgn, const string_t & _strEmail) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "email",       & rgn_extra_t::strEmail,       _strEmail));
}

void SetObjectWebPage  (rgn_t & _rgn, const string_t & _strWebPage) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "webpage",     & rgn_extra_t::strWebPage,     _strWebPage));
}

void SetObjectDescription (rgn_t & _rgn, const string_t & _strDescription) {
	PerformEditAction (new CChangeExtraAction<string_t>    (_rgn, "description", & rgn_extra_t::strDescription, _strDescription));
}

void ChangeCity       (rgn_t & _rgn, city_t * _pCity) {
	PerformEditAction (new CChangeExtraAction<city_t *>    (_rgn, "city",        & rgn_extra_t::pCity,          _pCity));
}

void ChangeZip        (rgn_t & _rgn, zip_t * _pZip) {
	PerformEditAction (new CChangeExtraAction<zip_t *>     (_rgn, "zip",         & rgn_extra_t::pZip,           _pZip));
}

void ChangeHighway    (rgn_t & _rgn, highway_t * _pHighway) {
	PerformEditAction (new CChangeExtraAction<highway_t *> (_rgn, "hw",          & rgn_extra_t::pHighway,       _pHighway));
}

void SetObjectRouteParams (rgn_t & _rgn, DWORD _dwRouteParams) {
	PerformEditAction (new CChangeExtraAction<DWORD>       (_rgn, "routeparam",  & rgn_extra_t::dwRouteParams,  _dwRouteParams));
}

void SetObjectRouteClass (rgn_t & _rgn, WORD _wRouteClass) {
	DWORD dwRouteParams;
	{
		const DWORD dwSave = _rgn.pExtra->dwRouteParams;
		_rgn.pExtra->fRouteClass = _wRouteClass;
		dwRouteParams = _rgn.pExtra->dwRouteParams;
		_rgn.pExtra->dwRouteParams = dwSave;
	}
	PerformEditAction (new CChangeExtraAction<DWORD>       (_rgn, "route class", & rgn_extra_t::dwRouteParams,  dwRouteParams));
}

void SetObjectSpeedLimit (rgn_t & _rgn, WORD _wSpeedLimit) {
	DWORD dwRouteParams;
	{
		const DWORD dwSave = _rgn.pExtra->dwRouteParams;
		_rgn.pExtra->fSpeedLimit = _wSpeedLimit;
		dwRouteParams = _rgn.pExtra->dwRouteParams;
		_rgn.pExtra->dwRouteParams = dwSave;
	}
	PerformEditAction (new CChangeExtraAction<DWORD>       (_rgn, "speed limit", & rgn_extra_t::dwRouteParams,  dwRouteParams));
}

